/[editor]/tooltip/tooltip.lua

https://gitlab.com/yasin3223/mtasa-resources · Lua · 387 lines · 291 code · 70 blank · 26 comment · 80 complexity · a7bbf906b22f22339523a12a5fa62d0c MD5 · raw file

  1. -- Default values
  2. local DEFAULT_FRAME_COUNT = 10
  3. local DEFAULT_BACKGROUND = { r = 255, g = 255, b = 128 }
  4. local DEFAULT_FOREGROUND = { r = 0, g = 0, b = 0 }
  5. local DEFAULT_BORDER = { r = 0, g = 0, b = 0 }
  6. local FONT_SCALE = 1
  7. local FONT_NAME = "arial"
  8. -- Internal vars
  9. local isEventHandled = false
  10. local processTooltips
  11. --
  12. -- Utility functions
  13. --
  14. local function isValidTooltip(tooltip)
  15. if tooltip and isElement(tooltip) and getElementType(tooltip) == "__tooltip" then
  16. return true
  17. else
  18. return false
  19. end
  20. end
  21. local function colorToTable(color)
  22. color = math.floor(color)
  23. local result = {}
  24. result.a = math.floor(color / 16777216)
  25. color = color - (result.a * 16777216)
  26. result.r = math.floor(color / 65536)
  27. color = color - (result.r * 65536)
  28. result.g = math.floor(color / 256)
  29. color = color - (result.g * 256)
  30. result.b = color
  31. return result
  32. end
  33. local function linesIterator(str)
  34. local i,j = 0,0
  35. local _
  36. local finished = false
  37. return function()
  38. if finished then return nil end
  39. i = j + 1
  40. _,j = string.find(str, "\n", i)
  41. if not j then
  42. finished = true
  43. return i, #str
  44. else
  45. return i,j-1
  46. end
  47. end
  48. end
  49. local function getTooltipBestSizeForText(text)
  50. local width
  51. local height
  52. local numlines = 0
  53. for i,j in linesIterator(text) do
  54. local substr = string.sub(text, i, j)
  55. local tempwidth = dxGetTextWidth(substr, FONT_SCALE, FONT_NAME)
  56. if not width or tempwidth > width then
  57. width = tempwidth
  58. end
  59. numlines = numlines + 1
  60. end
  61. height = dxGetFontHeight(FONT_SCALE, FONT_NAME) * numlines
  62. return (width or 0), height
  63. end
  64. --
  65. -- Interface functions
  66. --
  67. function Create(x, y, text, _foreground, _background, _border)
  68. if not x or not y or not text
  69. or type(x) ~= "number" or type(y) ~= "number" or type(text) ~= "string"
  70. then
  71. return false
  72. end
  73. local w, h = guiGetScreenSize()
  74. if x < 0 then x = 0 end
  75. if x > w then x = w end
  76. if y < 0 then y = 0 end
  77. if y > h then y = h end
  78. x = math.floor(tonumber(x))
  79. y = math.floor(tonumber(y))
  80. text = tostring(text)
  81. local foreground
  82. local background
  83. local border
  84. if _foreground and type(_foreground) == "number" then
  85. foreground = colorToTable(_foreground)
  86. else
  87. foreground = DEFAULT_FOREGROUND
  88. end
  89. if _background and type(_background) == "number" then
  90. background = colorToTable(_background)
  91. else
  92. background = DEFAULT_BACKGROUND
  93. end
  94. if _border and type(_border) == "number" then
  95. border = colorToTable(_border)
  96. else
  97. border = DEFAULT_BORDER
  98. end
  99. local newTooltip = createElement("__tooltip")
  100. setElementData(newTooltip, "x", x)
  101. setElementData(newTooltip, "y", y)
  102. setElementData(newTooltip, "text", text)
  103. setElementData(newTooltip, "state", "hidden")
  104. setElementData(newTooltip, "framesToFade", 0)
  105. setElementData(newTooltip, "framesFaded", 0)
  106. setElementData(newTooltip, "background", background)
  107. setElementData(newTooltip, "foreground", foreground)
  108. setElementData(newTooltip, "border", border)
  109. local width, height = getTooltipBestSizeForText(text)
  110. setElementData(newTooltip, "width", width)
  111. setElementData(newTooltip, "height", height)
  112. return newTooltip
  113. end
  114. function FadeIn(tooltip, frames)
  115. if not frames then frames = DEFAULT_FRAME_COUNT end
  116. if type(frames) ~= "number" then
  117. return false
  118. end
  119. if frames < 1 then frames = 1 end
  120. if isValidTooltip(tooltip) then
  121. setElementData(tooltip, "state", "faddingin")
  122. setElementData(tooltip, "framesToFade", math.floor(tonumber(frames)))
  123. setElementData(tooltip, "framesFaded", 0)
  124. if not isEventHandled then
  125. addEventHandler("onClientRender", getRootElement(), processTooltips)
  126. isEventHandled = true
  127. end
  128. return true
  129. else
  130. return false
  131. end
  132. end
  133. function FadeOut(tooltip, frames)
  134. if not frames then frames = DEFAULT_FRAME_COUNT end
  135. if type(frames) ~= "number" then
  136. return false
  137. end
  138. if frames < 1 then frames = 1 end
  139. if isValidTooltip(tooltip) then
  140. setElementData(tooltip, "state", "faddingout")
  141. setElementData(tooltip, "framesToFade", math.floor(tonumber(frames)))
  142. setElementData(tooltip, "framesFaded", 0)
  143. if not isEventHandled then
  144. addEventHandler("onClientRender", getRootElement(), processTooltips)
  145. isEventHandled = true
  146. end
  147. return true
  148. else
  149. return false
  150. end
  151. end
  152. function GetState(tooltip)
  153. if isValidTooltip(tooltip) then
  154. return getElementData(tooltip, "state")
  155. else
  156. return false
  157. end
  158. end
  159. function SetPosition(tooltip, x, y)
  160. if isValidTooltip(tooltip)
  161. and x and y
  162. and type(x) == "number" and type(y) == "number"
  163. then
  164. local w, h = guiGetScreenSize()
  165. if x < 0 then x = 0 end
  166. if x > w then x = w end
  167. if y < 0 then y = 0 end
  168. if y > h then y = h end
  169. setElementData(tooltip, "x", math.floor(tonumber(x)))
  170. setElementData(tooltip, "y", math.floor(tonumber(y)))
  171. return true
  172. else
  173. return false
  174. end
  175. end
  176. function GetPosition(tooltip)
  177. if isValidTooltip(tooltip) then
  178. local x = getElementData(tooltip, "x")
  179. local y = getElementData(tooltip, "y")
  180. return x, y
  181. else
  182. return false
  183. end
  184. end
  185. function SetText(tooltip, text)
  186. if isValidTooltip(tooltip) and text and type(text) == "string" then
  187. setElementData(tooltip, "text", tostring(text))
  188. local width, height = getTooltipBestSizeForText(text)
  189. setElementData(tooltip, "width", width)
  190. setElementData(tooltip, "height", height)
  191. return true
  192. else
  193. return false
  194. end
  195. end
  196. function GetText(tooltip)
  197. if isValidTooltip(tooltip) then
  198. return getElementData(tooltip, "text")
  199. else
  200. return false
  201. end
  202. end
  203. --
  204. -- Color setting/getting interface functions
  205. --
  206. local function setTooltipColor(tooltip, colorname, color)
  207. if isValidTooltip(tooltip) and color and type(color) == "number" then
  208. setElementData(tooltip, colorname, colorToTable(color))
  209. return true
  210. else
  211. return false
  212. end
  213. end
  214. local function getTooltipColor(tooltip, colorname)
  215. if isValidTooltip(tooltip) then
  216. local color = getElementData(tooltip, colorname)
  217. return color.r, color.g, color.b
  218. else
  219. return false
  220. end
  221. end
  222. function SetForegroundColor(tooltip, color)
  223. return setTooltipColor(tooltip, "foreground", color)
  224. end
  225. function GetForegroundColor(tooltip)
  226. return getTooltipColor(tooltip, "foreground")
  227. end
  228. function SetBackgroundColor(tooltip, color)
  229. return setTooltipColor(tooltip, "background", color)
  230. end
  231. function GetBackgroundColor(tooltip)
  232. return getTooltipColor(tooltip, "background")
  233. end
  234. function SetBorderColor(tooltip, color)
  235. return setTooltipColor(tooltip, "border", color)
  236. end
  237. function GetBorderColor(tooltip)
  238. return getTooltipColor(tooltip, "border")
  239. end
  240. --
  241. -- processTooltips
  242. -- Event called for every frame to draw with directx the tooltips
  243. -- that should be drawn.
  244. --
  245. processTooltips = function()
  246. local tooltips = getElementsByType("__tooltip")
  247. if #tooltips == 0 then
  248. removeEventHandler("onClientRender", getRootElement(), processTooltips)
  249. isEventHandled = false
  250. return
  251. end
  252. local existVisibleTooltips = false
  253. for k,tooltip in ipairs(tooltips) do
  254. local state = getElementData(tooltip, "state")
  255. local alpha = false
  256. if state == "visible" then
  257. -- If the state is visible we don't need to calculate any alpha value
  258. alpha = 255
  259. elseif state == "faddingin" then
  260. -- If it's still fadding in we must calculate the tooltip transparency
  261. local framesToFade = getElementData(tooltip, "framesToFade")
  262. local framesFaded = getElementData(tooltip, "framesFaded")
  263. framesFaded = framesFaded + 1
  264. if framesFaded >= framesToFade then
  265. -- When it has finished fadding in, set it as visible so we don't have to
  266. -- calculate the intermediate alpha values
  267. setElementData(tooltip, "state", "visible")
  268. alpha = 255
  269. else
  270. setElementData(tooltip, "framesFaded", framesFaded)
  271. alpha = math.floor(framesFaded * 255 / framesToFade)
  272. end
  273. elseif state == "faddingout" then
  274. -- If it's fadding out we must calculate the tooltip transparency
  275. local framesToFade = getElementData(tooltip, "framesToFade")
  276. local framesFaded = getElementData(tooltip, "framesFaded")
  277. framesFaded = framesFaded + 1
  278. if framesFaded >= framesToFade then
  279. -- When it has finished fadding out, set it as hidden so it won't be checked again
  280. setElementData(tooltip, "state", "hidden")
  281. alpha = false
  282. else
  283. setElementData(tooltip, "framesFaded", framesFaded)
  284. alpha = math.floor(255 - (framesFaded * 255 / framesToFade))
  285. end
  286. end
  287. -- Alpha can be false if the tooltip state is unknown or hidden
  288. if alpha then
  289. local x = getElementData(tooltip, "x")
  290. local y = getElementData(tooltip, "y")
  291. local text = getElementData(tooltip, "text")
  292. local background = getElementData(tooltip, "background")
  293. local foreground = getElementData(tooltip, "foreground")
  294. local border = getElementData(tooltip, "border")
  295. local width = getElementData(tooltip, "width")
  296. local height = getElementData(tooltip, "height")
  297. local borderColor = tocolor(border.r, border.g, border.b, alpha)
  298. local backColor = tocolor(background.r, background.g, background.b, alpha)
  299. local foreColor = tocolor(foreground.r, foreground.g, foreground.b, alpha)
  300. existVisibleTooltips = true
  301. -- Draw the tooltip borders
  302. dxDrawLine(x, y, x + width + 6, y, borderColor, 1, true)
  303. dxDrawLine(x, y + height + 4, x + width + 6, y + height + 4, borderColor, 1, true)
  304. dxDrawLine(x, y, x, y + height + 4, borderColor, 1, true)
  305. dxDrawLine(x + width + 6, y, x + width + 6, y + height + 4, borderColor, 1, true)
  306. -- Draw the tooltip background
  307. dxDrawRectangle(x + 1, y + 1, width + 4, height + 2, backColor, true)
  308. -- Draw the tooltip text
  309. dxDrawText(text, x + 3, y + 2, x + 3 + width, y + 2 + height, foreColor,
  310. FONT_SCALE, FONT_NAME, "left", "top", false, false, true)
  311. end
  312. end
  313. if not existVisibleTooltips then
  314. removeEventHandler("onClientRender", getRootElement(), processTooltips)
  315. isEventHandled = false
  316. end
  317. end